#! /usr/bin/perl -si.bak
use strict;
use warnings;

our $VERSION = '0.01';

use vars qw($h $H $R $C $L $E);

defined($h) && die "$0 -h(elp) -H(andle) -C(omment) (c)-L(asses) -R(eport) -E(dit)";

my $bundle;
my $promise_type;
my $promise;
my $comment;
my $classes;
my $handle;
my $reports;

# states in finite state machine
my $s_init         = 1;
my $s_bundle       = 2;
my $s_promise_type = 3;
my $s_shortpromise = 4;
my $s_longpromise  = 5;
my $s_body         = 6;

for ( my $s = $s_init ; <> ; print ) {
    if (/^\s*#/) {
s/vim:.*/vim: tabstop=2 shiftwidth=2 smarttab expandtab softtabstop=2 autoindent/;
        $s = $s;
        next;
    }
    if ( $s == $s_init and /^\s*bundle/ ) {
        s/^\s*//;
        s/\s*$/ {\n/ if not /{/;    # ensure K&R Style
        my @words = split(/\W+/);
        $bundle  = $words[2] if ( $words[1] eq "agent" );
        $reports = "";
        $s       = $s_bundle;
        next;
    }
    if ( $s == $s_bundle and /^\s*{\s*$/ ) {
        $_ = "";                    # ensure K&R Style
        $s = $s;
        next;
    }
    if ( ( $s == $s_promise_type or $s == $s_bundle ) and /[^:]:\s*$/ ) {
        s/^\s*//;
        $promise_type = $_;
        $promise_type =~ s/^\s*//;
        $promise_type =~ s/:[^:]*$//;
        $s = $s_promise_type;
        next;
    }
    if ( ( $s == $s_promise_type or $s == $s_body ) and /::\s*$/ ) {
        s/^\s*/  /;
        $s = $s;
        next;
    }
    if ( $s == $s_promise_type and /^\s*"/ ) {
        s/^\s*/    /;
        $_ = formatLine( $_, "    " );
        if (/"\s*$/) {
            $promise = $_;
            $promise =~ s/^\s*"//;
            $promise =~ s/"[^"]*$//;
            $handle  = "";
            $classes = "";
            $comment = "";
            $s       = $s_longpromise;
            next;
        }
        elsif (/;\s*$/) {
            $s = $s_promise_type;
            next;
        }
        else {
            $s = $s_shortpromise;
            next;
        }
    }
    if ( $s == $s_shortpromise ) {
        if (/;\s*$/) {
            $s = $s_promise_type;
            next;
        }
        else {
            $s = $s_shortpromise;
            next;
        }
    }
    if ( $s == $s_longpromise ) {
        if (/=>/) {
            unless (/[,;]\s$/) {
                chomp;
                $_ .= <>;
            }
            my @words = split(/\W+/);
            if ( $words[1] eq "comment" ) {
                $comment = $_;
                $comment =~ s/^[^"]*"//;
                $comment =~ s/"[^"]*$//;
            }
            if ( $words[1] eq "classes" ) {
                $classes = $_;
                $classes =~ s/^[^"]*"//;
                $classes =~ s/"[^"]*$//;
            }
            if ( $words[1] eq "handle" ) {
                $handle = $_;
                $handle =~ s/^[^"]*"//;
                $handle =~ s/"[^"]*$//;
            }
            s/^\s*/      /;
            $_ = formatLine( $_, "      " );
        }
        else {
            s/^\s*/        /;
        }
        if (/;\s*$/) {
            if ( defined($C) and not "$comment" ) {
                $comment = qq($bundle $promise_type '$promise');
                print STDERR
                  "missing \"comment\" $comment\n";
                if ( defined($E) ) {
                    my $line = formatLine( qq(      comment => "$comment";\n),
                        "      " );
                    s/;\s*$/,\n$line/;
                }
            }
            if ( defined($H) and not "$handle" ) {
                $handle = "${bundle}_${promise_type}_${promise}";
                print STDERR
                  "missing \"handle\" $handle\n";
                if ( defined($E) ) {
                    $handle =~ s/\W/_/g;
                    my $line =
                      formatLine( qq(      handle => "$handle";\n), "      " );
                    s/;\s*$/,\n$line/;
                }
            }
            if ( defined($L) and not "$classes" ) {
                $classes = "$handle";
                print STDERR
                  "missing \"classes\" $classes\n";
                if ( defined($E) and "$handle" ) {
                    my $line = formatLine(
                        qq(      classes => result_classes_name("$classes");\n),
                        "      "
                    );
                    s/;\s*$/,\n$line/;
                }
            }
            if ( defined($R) and "$handle" and "$comment" ) {
                print STDERR "insert \"report\" ${handle}: ${comment}\n";
                my $line = formatLine(
qq(    "\$(results): $comment" ifvarclass => "\$(results)_$handle";\n),
                    "    "
                );
                $reports .= $line;
            }
            $s = $s_promise_type;
        }
        else {
            $s = $s_longpromise;
        }
        next;
    }
    if (    defined($E)
        and $s == $s_promise_type
        and /}\s*$/
        and $promise_type eq "reports"
        and "$reports" ne "" )
    {
        s/^\s*/  agent::\n$reports/;
        $s = $s_init;
        next;
    }
    if ( $s == $s_init and /^\s*(body)/ ) {
        s/^\s*//;
        s/\s*$/ {\n/ if not /{/;    # ensure K&R Style
        $s = $s_body;
        next;
    }
    if ( $s == $s_body and /^\s*{\s*$/ ) {
        $_ = "";                    # ensure K&R Style
        $s = $s;
        next;
    }
    if ( $s == $s_body ) {
        if (/}\s*$/) {
            s/^\s*//;
            $s = $s_init;
        }
        else {
            s/^\s*/    /;
            $s = $s_body;
        }
        next;
    }
}

sub formatLine {
    my $line   = shift;
    my $einzug = shift;

    $line =~ s/\h+=>/ =>/;
    if ( length($line) > 80 ) {
        $line =~ s/=>\h+/=>\n  $einzug/;
    }
    else {
        $line =~ s/=>\h+/=> /;
    }

    return $line;
}

# vim: tabstop=2 shiftwidth=2 smarttab expandtab softtabstop=2 autoindent
